/*
 * RelativeLayout.h
 *
 *  Created on: 2012-10-25
 *      Author: yangentao@gmail.com
 */

#ifndef RELATIVELAYOUT_H_
#define RELATIVELAYOUT_H_
#include <limits.h>
#include "Layout.h"

#define INVALID_EDGE  INT_MIN

class Window;

class RelativeSizeValue {
public:
	RelativeSizeValue();
	//fill parent
	RelativeSizeValue& fill();
	//rate <0;
	//if rate == -3, it means 1/3 of parent width(or height)
	RelativeSizeValue& fill(int rate);

	int calcSize(int parentWidthOrHeight);
	//fill parent
	bool isFill() const;
	bool isFix() const;
	//fix value
	int fixValue() const;
	//fix value
	void fixValue(int val);

	RelativeSizeValue& limit(int minValue, int maxValue = 0);
private:
	int value;
public:
	int minLimit;	//>=0
	int maxLimit;	//>=0
};

class RelativeParam: public LayoutParam {
public:
	RelativeParam();
public:
	RelativeSizeValue width;
	RelativeSizeValue height;
public:
	bool alignParentLeft; //left  = 0
	bool alignParentRight; //right = parentClientWidth
	bool alignParentTop; //top =0
	bool alignParentBottom; //bottom = parentClientHeight
	bool centerHor; //center in hor  ,
	bool centerVer; //center in ver
	bool centerInParent; //if this is true, centerHor and centerVer will be ignored

	Window* toAnchorLeft; //right = anchor.left
	Window* toAnchorRight; //left = anchor.right
	Window* toAnchorTop; //above  bottom = anchor.top
	Window* toAnchorBottom; //bellow  top = anchor.bottom

	//alignAnchorXXX will cover  toAnchorXXX when conflict
	//etc. alignAnchorLeft  will  cover toAnchorRight
	Window* alignAnchorLeft;	//left = anchor.left
	Window* alignAnchorRight;	//right = anchor.right
	Window* alignAnchorTop;	//top = anchor.top
	Window* alignAnchorBottom;	//bottom = anchor.bottom
private:
	friend class RelativeLayout;
	Rect rect;
	bool leftEnable;
	bool rightEnable;
	bool topEnable;
	bool bottomEnable;
	void clear();
};
class RelativeLayout: public Layout {
public:
	RelativeLayout();
	virtual ~RelativeLayout();
public:
	void layout(Window* parent);

private:
	void getDepends(Window* w, Vector<Window*>& horVec, Vector<Window*>& verVec);
	void calcFix(RelativeParam* p, Rect clientRect);
	void fixOne(Window* child, Window* parent);
	void fixChildren(const Vector<Window*>& children, Window* parent);
	void doMove(const Vector<Window*>& children, Window* parent);
	bool checkCircle(const Vector<Window*>& children, Window* parent);
};

//--------------------inline implements------------------------

inline RelativeSizeValue::RelativeSizeValue() {
	value = 0;
	minLimit = maxLimit = 0;
}
inline RelativeSizeValue& RelativeSizeValue::fill() {
	value = FILL_PARENT;
	return *this;
}
//rate <0;
//if rate == -3, it means 1/3 of parent width(or height)
inline RelativeSizeValue& RelativeSizeValue::fill(int rate) {
	assert(rate < 0);
	value = rate;
	return *this;
}
inline int RelativeSizeValue::calcSize(int parentWidthOrHeight){
	assert(value < 0);
	parentWidthOrHeight = Max(0, parentWidthOrHeight);
	return -parentWidthOrHeight / value;
}
inline bool RelativeSizeValue::isFill() const {
	return value < 0;
}
inline bool RelativeSizeValue::isFix() const {
	return value >= 0;
}
inline int RelativeSizeValue::fixValue() const {
	assert(value >=0);
	return value;
}
inline void RelativeSizeValue::fixValue(int val) {
	assert(val>=0);
	value = val;
}

inline RelativeSizeValue& RelativeSizeValue::limit(int minValue, int maxValue) {
	assert(minValue >=0);
	assert(maxValue >=0);
	minLimit = minValue;
	maxLimit = maxValue;
	return *this;
}

inline RelativeParam::RelativeParam() {
	type = relativeLayoutParam;

	alignParentLeft = false;
	alignParentRight = false;
	alignParentTop = false;
	alignParentBottom = false;
	centerHor = false;
	centerVer = false;
	centerInParent = false;

	toAnchorLeft = 0;
	toAnchorRight = 0;
	toAnchorTop = 0;
	toAnchorBottom = 0;

	alignAnchorLeft = 0;
	alignAnchorRight = 0;
	alignAnchorTop = 0;
	alignAnchorBottom = 0;
	clear();
}

inline void RelativeParam::clear() {
	leftEnable = false;
	rightEnable = false;
	topEnable = false;
	bottomEnable = false;

}

#endif /* RELATIVELAYOUT_H_ */
